package com.designschool.base.download;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile; 
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import com.designschool.base.notice.DownloadListener;

import android.R.bool;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

/***
 * 
 * @项目名:base  
 * 
 * @类名:Downloader.java  
 * 
 * @创建人:shibaotong
 *
 * @类描述:下载管理器类
 * 
 * @date:2013-11-20
 * 
 * @Version:1.0 
 *
 *****************************************
 */
public class Downloader implements Runnable{
    private String locationpath="";//本地路径
    private String url="";//下载路径
    private int thread_count=0;//开启下载线程数量
    private int filesize=0;//下载文件大小
    private DownloadListener downloadListener;
    private String title="";//下载文件标题
    private String id="";//下载文件与服务器之间唯一标识位
    
    private DownloadDao dao;
    private Context context;
    private Handler handler=new Handler();
    
    private static final int INIT = 1;//初始化状态，下载状态，暂停状态״̬
    private static final int DOWNLOADING = 2;
    private static final int PAUSE = 3;
    private int state = INIT;
    private Downloadinfo downloadinfo;
    private Downloadinfo info;
    private URL strUrl;
    private URLConnection connection; 
    private File file;
    private List<Downloadinfo> listDownloadinfos;
    
    public Downloader(String locationpath,String url,int thread_count,
            Context context,DownloadListener downloadListener)
    {
        this.context=context;
        this.locationpath=locationpath;
        this.url=url;
        this.thread_count=thread_count;
        this.downloadListener=downloadListener;
        dao=new DownloadDao(context); 
    }
    
    /***
     * 设置标题与唯一标志物
     * @param title
     * @param id
     */
    public void setTileid(String title,String id)
    {
        this.title=title;
        this.id=id;
    }
   
    private void setDowninfo(Downloadinfo info)
    {
        if(listDownloadinfos!=null&&listDownloadinfos.size()>0)
        {
            info.filepath=listDownloadinfos.get(0).filepath;
            info.url=listDownloadinfos.get(0).url;
            info.id=listDownloadinfos.get(0).id;
            info.title=listDownloadinfos.get(0).title;
            info.thread_id=listDownloadinfos.get(0).thread_id;
            info.fizesize=listDownloadinfos.get(0).fizesize; 
            info.progess=getProgess(); 
        }
    }
            
    private int getProgess()
    { 
        int progess=0; 
            if(listDownloadinfos!=null&&listDownloadinfos.size()>0)
            {
                for(int pos=0;pos<listDownloadinfos.size();pos++)
                {
                    progess+=listDownloadinfos.get(pos).progess;
                } 
            }
        return progess;
    }
    
    
    public void down()
    {
        if(listDownloadinfos!=null&&listDownloadinfos.size()>0)
        {
            if(state==DOWNLOADING)
            {
                return;
            }
            state=DOWNLOADING;
            for(int ii=0;ii<listDownloadinfos.size();ii++)
            {
                new Thread(new DownloadThread(listDownloadinfos.get(ii))).start(); 
            }
            
        }
    }
   /***
    * 
    * @项目名:base  
    * 
    * @类名:Downloader.java  
    * 
    * @创建人:shibaotong
    *
    * @类描述:开启下载线程
    * 
    * @date:2013-11-20
    * 
    * @Version:1.0 
    *
    *****************************************
    */
    class DownloadThread implements Runnable{
        
        private Downloadinfo downinfo;
        
        public DownloadThread(Downloadinfo downinfo)
        {
            this.downinfo=downinfo;
        }

        @Override
        public void run() { 
            URLConnection connection = null;
            RandomAccessFile randomAccessFile = null;
            InputStream is = null;
            try { 
                URL url = new URL(downinfo.url);
                connection =   url.openConnection();
                connection.setConnectTimeout(5000);  
                
//                // 下载断点 
                connection.setRequestProperty("RANGE", "bytes="
                        + (downinfo.start_pos + downinfo.progess) + "-" + downinfo.end_pos);
                connection.connect();
              
                randomAccessFile = new RandomAccessFile(downinfo.filepath, "rwd");
                randomAccessFile.seek(downinfo.start_pos + downinfo.progess);
                // 得到输入流
                is = connection.getInputStream();
                byte[] buffer = new byte[4096];
                int length = -1;
                while ((length = is.read(buffer)) != -1) {
                    randomAccessFile.write(buffer, 0, length);
                    downinfo.progess += length;
                    //更新数据库信息
                    Update(downinfo); 
                    info.progess=getProgess();
                    // 回调下载信息
                   downloadListener.sendSize(info);
                    if (state == PAUSE) {
                        return;
                    }
                }
                downinfo.status="完毕";
                Update(downinfo); 
            } catch (Exception e) {
                downloadListener.Error(e);
                e.printStackTrace();
            } finally {
                try {
                    is.close();
                    randomAccessFile.close(); 
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }
        
    }
    
    
    /***
     *判断是否在线下载״̬
     * @return
     */
    public boolean isDownloading()
    {
        return state==DOWNLOADING;
    }

    /**
     * 判断是否第一次下载
     * @param url
     * @return
     */
    private boolean Isinit(final String url)
    {
        if(!dao.Findinfo(url))
        {
           file=new File(locationpath);
           if(!file.exists())
           {
               dao.Delete(url);
               return true;
           }
           else{
               handler.post(new Runnable() { 
                @Override
                public void run() { 
                    if(dao.getInfos(url).get(0).status.equals("完毕"))
                    {
                    Toast.makeText(context, "下载已存在，无需下载！", 800).show();
                    }
                }
            });
               return false;
           }
        }
        return true;
    }
    
    /**
     * 删除数据库下载信息
     * @param urlstr
     */
    public void delete(String url) {
        dao.Delete(url);
    }

    //暂停下载
    public void pause() {
        state = PAUSE;
    }

    //重置下载״̬
    public void reset() {
        state = INIT;
    }

    @Override
    public void run() { 
        /**
        * 判断是否第一下载
        */
       if(Isinit(url))
       {
           /***
            * 初始化下载信息
            */
           try { 
               strUrl=new URL(url);
               connection= strUrl.openConnection();
               connection.setConnectTimeout(5000);
               connection.connect();
               filesize=connection.getContentLength();
               file=new File(locationpath);
               file.getParentFile().mkdirs();
               if (!file.exists()) {
                   file.createNewFile();
               } 
               RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
               accessFile.setLength(filesize);
               accessFile.close();
               
           } catch (Exception e) { 
               downloadListener.Error(e);
               e.printStackTrace();
           } 
           
           int range = filesize / thread_count;
           listDownloadinfos = new ArrayList<Downloadinfo>();
           for (int i = 0; i < thread_count - 1; i++) {
               downloadinfo= new Downloadinfo(i, i * range, (i + 1)
                       * range - 1, filesize, title,id,url,locationpath);
               listDownloadinfos.add(downloadinfo); 
           }
           downloadinfo = new Downloadinfo(thread_count-1, (thread_count-1) * range, filesize - 1, filesize, title,id,url,locationpath);
           listDownloadinfos.add(downloadinfo);
           // 添加下载信息
           dao.addInfos(listDownloadinfos); 
           info=new Downloadinfo(thread_count,0,filesize-1,filesize,title,id,url,locationpath);
       }else{ 
           listDownloadinfos=dao.getInfos(url); 
           info=new Downloadinfo();
           setDowninfo(info);
       }
       down();
    }
    
    private void Update(Downloadinfo loadinfo)
    {
            dao.Update(loadinfo.url, loadinfo.progess, loadinfo.status);
    }
      
}
